<?php
/**
 * @author spenceryg
 * @date 2022/11/26
 * @time 10:12 下午
 * @focus love & life
 */


namespace app\auto\business;




use app\auto\model\App;
use app\auto\model\Controller;
use app\auto\model\Field;
use app\auto\model\Relation;
use app\auto\model\Table;
use app\auto\validate\TableValidate;
use app\common\lib\mysql\TableParse;
use app\common\lib\mysql\TpTableModify;
use app\common\lib\SpTranslate;
use Exception;
use ShaoZeMing\Translate\Exceptions\TranslateException;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\exception\ValidateException;
use think\facade\Db;
use think\helper\Str;

class TableBusiness
{
    public static $model = "app\\auto\\model\\Table";

    use \app\common\traits\business\BusinessTrait;

    public static $truncate_tables = [
        'auto_table',
        'auto_field',
        'auto_relation',
        'auto_controller',
        'auto_method',
        'auto_method_field',
        'db_admin_file',
        'db_admin_node'
    ];


    /**
     * 截断auto相关表
     * truncateTables
     * @throws Exception
     */
    public static function truncateTables()
    {
        foreach (self::$truncate_tables as $table_name) {
            (new TpTableModify($table_name))->truncate()->execute();
        }
    }


    /**
     * add
     * @param $data
     * @return mixed
     * @throws Exception
     */
    public static function add($data)
    {
        validate(TableValidate::class)->check($data);
        $exist = Table::getByName($data['name']);
        if($exist) {
            throw new ValidateException('表'.$data['name'].'已存在');
        }
        $model = self::$model::create($data);
        // 创建表 和 基础字段
        self::createTable($data['name'], $data['comment']);
        // 创建对应应用的控制器
        self::createAppController($data);
        return $model;
    }


    /**
     * 快速添加
     * fastAdd
     * @param $data
     */
    public static function fastAdd($data)
    {
        foreach ($data['name'] as $key=>$name) {
            if($name) {
                $this_data = [
                    'name' => $name,
                    'comment' => $data['comment'][$key],
                    'apps' => $data['apps']
                ];
                try {
                    self::add($this_data);
                } catch (\Exception $e) {
                    continue;
                }

            }
        }
    }





    /**
     * 创建对应app的controller（数据表添加）
     * createAppController
     * @param $data
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public static function createAppController($data)
    {
        if($data['apps']) {
            $apps = $data['apps'];
            $class_name = self::tableToClass($data['name']);
            $comment = $data['comment'];
            foreach ($apps as $app) {
                $this_app = App::find($app);
                $this_app->controller()->save([
                    'name' => $class_name,
                    'comment' => $comment
                ]);
            }
        }
    }


    /**
     * 删除对应的应用控制器
     * removeAppController
     * @param $table_name
     */
    public static function removeAppController($table_name)
    {
        $class_name = self::tableToClass($table_name);
        $ids = Controller::where('name', $class_name)->column('id');
        // 控制器模型之beforeDelete 做删除其他操作
        Controller::destroy($ids);
    }


    /**
     * createTable
     * @param $tableName
     * @param $comment
     * @throws Exception
     */
    private static function createTable($tableName, $comment)
    {
        $tables = TableParse::getTables();
        if (in_array($tableName, $tables)) {
            throw new Exception('表已存在');
        }
        $tableGenerator = new TpTableModify($tableName);
        $tableGenerator->createTable($comment)->execute();

        // 默认添加
        // id
        self::createFieldId($tableName);
        // auto_time
        self::addAutoTimeField($tableName);
        // soft_delete
        self::addSoftDeleteField($tableName);
        // pubid
        self::addPubField($tableName);
        // sort
//        self::addSortField($tableName);
        // 增加默认字段name
        self::createFieldStr($tableName, 'name', '名称');

    }


    /**
     * setSysField
     * @param $data
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public static function setSysField($data)
    {
        $id = $data['id'];
        $table_name = Table::find($id)['name'];
        $name = $data['name'];
        $status = $data['is_show'];
        switch ($name) {
            case 'is_auto_time':
                !$status ? self::removeAutoTimeField($table_name) : self::addAutoTimeField($table_name);
                break;
            case 'is_soft_delete':
                !$status ? self::removeSoftDeleteField($table_name) : self::addSoftDeleteField($table_name);
                break;
            case 'is_pubid':
                !$status ? self::removePubField($table_name) : self::addPubField($table_name);
                break;
            case 'is_sort':
                !$status ? self::removeSortField($table_name) : self::addSortField($table_name);
                break;
            case 'is_tree_sort':
                !$status ? self::removeTreeSortField($table_name) : self::addTreeSortField($table_name);
                break;
            default:
                throw new ValidateException('非法name:' . $name);
        }
        Table::update([
            'id' => $id,
            $name => $status
        ]);
    }


    /**
     * delete
     * @param $id
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public static function delete($id)
    {
        $table = Table::find($id);
        $table_name = $table->name;
        // 删除对应的应用的控制器
        self::removeAppController($table_name);
        // 先删除相关关系
        $relation_ids = Relation::where('table_id_master|table_id_sliver|table_id_middle', '=' ,$id)->column('id');
        foreach ($relation_ids as $relation_id) {
            RelationBusiness::delete($relation_id);
        }
        // 删除前先删除字段
        $table->delete();
        // 删除表
        self::dropTable($table_name);
        // 删除模型
        self::deleteModelFile($table_name);

    }


    public static function deleteModelFile($table_name)
    {
        $class_name = Str::studly(str_replace(env('DATABASE.PREFIX'), '', $table_name));
        $path = '../app/common/model/';
        $filename = $path . $class_name . '.php';
        unlink($filename);
    }


    /**
     * deleteAll
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public static function deleteAll()
    {
        $tables = Table::select();
        foreach ($tables as $table) {
            self::delete($table->getAttr('id'));
        }
        self::truncateTables();
        $sql_arr = <<<EOF
INSERT INTO `db_admin_node` VALUES (1, '系统设置', 'sys.adminNode/index', 0, 1671542616, NULL, NULL, 10, NULL, NULL, NULL, 1, 'layui-icon-console', 1, NULL);
INSERT INTO `db_admin_node` VALUES (2, '菜单管理', 'sys.adminNode/index', 1, 1671542616, NULL, 1644201918, 10, NULL, NULL, NULL, 2, 'layui-icon-template-1', 1, NULL);
INSERT INTO `db_admin_node` VALUES (3, '用户管理', 'sys.adminUser/index', 1, 1671542616, NULL, 1644201966, 20, NULL, NULL, NULL, 2, 'layui-icon-username', 1, NULL);
INSERT INTO `db_admin_node` VALUES (4, '权限管理', 'sys.adminAccess/index', 1, 1671542616, NULL, 1644202093, 30, NULL, NULL, NULL, 2, 'layui-icon-code-circle', 1, NULL);
INSERT INTO `db_admin_node` VALUES (5, '角色管理', 'sys.adminRole/index', 1, 1671542616, NULL, 1644202128, 40, NULL, NULL, NULL, 2, 'layui-icon-face-surprised', 1, NULL);
INSERT INTO `db_admin_node` VALUES (6, '自动生成', 'auto/table/index', 0, 1671542616, NULL, 1669632793, 20, NULL, NULL, NULL, 1, 'layui-icon-template-1', 1, NULL);
INSERT INTO `db_admin_node` VALUES (7, '配置管理 ', 'admin/sys.SpConfig/index', 1, 1682256733, NULL, 1682256717, 50, NULL, NULL, NULL, 2, 'layui-icon-template-1', 1, NULL);
EOF;
        foreach (explode("\n", $sql_arr) as $sql){
            Db::execute($sql);
        }

    }


    /**
     * dropTable
     * @param $tableName
     * @throws Exception
     */
    public static function dropTable($tableName)
    {
        $tables = TableParse::getTables();
        if (in_array($tableName, $tables)) {
            $tableGenerator = new TpTableModify($tableName);
            $tableGenerator->dropTable()->execute();
        }
    }


    /**
     * addSoftDeleteField
     * @param $table_name
     * @throws Exception
     */
    public static function addSoftDeleteField($table_name)
    {
        self::createFieldInt($table_name, 'delete_time','软删除时间');
    }


    /**
     * removeSoftDeleteField
     * @param $table_name
     * @throws Exception
     */
    public static function removeSoftDeleteField($table_name)
    {
        self::deleteField($table_name, 'delete_time');
    }


    /**
     * addAutoTimeField
     * @param $table_name
     * @throws Exception
     */
    public static function addAutoTimeField($table_name)
    {
        self::createFieldInt($table_name, 'create_time','创建时间');
        self::createFieldInt($table_name, 'update_time','更新时间');
    }


    /**
     * removeAutoTimeField
     * @param $table_name
     * @throws Exception
     */
    public static function removeAutoTimeField($table_name)
    {
        self::deleteField($table_name, 'create_time');
        self::deleteField($table_name, 'update_time');
    }


    /**
     * addTreeSortField
     * @param $table_name
     * @throws Exception
     */
    public static function addTreeSortField($table_name)
    {
        self::createFieldInt($table_name, 'pid','父级id', 0);
    }

    /**
     * removeTreeSortField
     * @param $table_name
     * @throws Exception
     */
    public static function removeTreeSortField($table_name)
    {
        self::deleteField($table_name, 'pid');
    }


    /**
     * addSortField
     * @param $table_name
     * @throws Exception
     */
    public static function addSortField($table_name)
    {
        self::createFieldInt($table_name, 'sort','排序字段', 0);


    }

    /**
     * removeSortField
     * @param $table_name
     * @throws Exception
     */
    public static function removeSortField($table_name)
    {
        self::deleteField($table_name, 'sort');
    }


    /**
     * addPubField
     * @param $table_name
     * @throws Exception
     */
    public static function addPubField($table_name)
    {
        self::createFieldStr($table_name, 'pubid','公共id标识', 0);
    }

    /**
     * removePubField
     * @param $table_name
     * @throws Exception
     */
    public static function removePubField($table_name)
    {
        self::deleteField($table_name, 'pubid');
    }





    /**
     * 创建int类型字段
     * createFieldInt
     * @param $table_name
     * @param $name
     * @param $comment
     * @param null $default
     * @throws Exception
     */
    public static function createFieldInt($table_name, $name, $comment, $default = null)
    {
        FieldBusiness::add([
            'name' => $name,
            'comment' => $comment,
            'type' => 'int',
            'length' => '11',
            'default' => $default,
            'is_null' => 1,
            'table_id' => Table::getByName($table_name)['id'],
            'is_sys' => 1,
            'sort' => 0
        ]);
    }


    /**
     * createFileStr
     * @param $table_name
     * @param $name
     * @param $comment
     * @param null $default
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public static function createFieldStr($table_name, $name, $comment, $default = null){
        FieldBusiness::add([
            'name' => $name,
            'comment' => $comment,
            'type' => 'varchar',
            'length' => '255',
            'default' => $default,
            'is_null' => 1,
            'table_id' => Table::getByName($table_name)['id'],
            'is_sys' => 0,
            'sort' => 10
        ]);
    }


    /**
     * createFieldId
     * @param $table_name
     * @param $name
     * @param $comment
     * @param null $default
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public static function createFieldId($table_name)
    {
        Field::create([
            'name' => 'id',
            'comment' => '编号',
            'type' => 'int',
            'length' => '11',
            'default' => '',
            'is_null' => 0,
            'table_id' => Table::getByName($table_name)['id'],
            'is_sys' => 1,
            'sort' => 0
        ]);
    }


    /**
     * 删除表字段
     * deleteField
     * @param $table_name
     * @param $field_name
     * @throws Exception
     */
    public static function deleteField($table_name, $field_name)
    {
        Field::destroy(function ($query) use ($table_name,$field_name) {
            $query->where('table_id', Table::getByName($table_name)['id'])
                ->where('name',$field_name);
        });
    }


    /**
     * 表名转换为类名
     * tableToClass
     * @param $table_name
     * @return string
     */
    public static function tableToClass($table_name): string
    {
        $prefix = env('DATABASE.PREFIX');
        $table_no_prefix = str_replace($prefix, '', $table_name);
        return Str::studly($table_no_prefix);
    }


    /**
     * 表名转换为关联函数名
     * tableToRelation
     * @param $table_name
     * @return string
     */
    public static function tableToRelation($table_name): string
    {
        $prefix = env('DATABASE.PREFIX');
        $table_no_prefix = str_replace($prefix, '', $table_name);
        return Str::camel($table_no_prefix);
    }

    /**
     * 表获取表id
     * tableToId
     * @param $table_name
     * @return string
     */
    public static function tableToId($table_name): string
    {
        $prefix = env('DATABASE.PREFIX');
        $table_no_prefix = str_replace($prefix, '', $table_name);
        return$table_no_prefix . '_id';
    }


}
